<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="zh-CN" />
<link href="../style/css/manual-zip.css" rel="stylesheet" media="all" type="text/css" title="Main stylesheet" />
<link href="../style/css/manual-zip-100pc.css" rel="alternate stylesheet" media="all" type="text/css" title="No Sidebar - Default font size" />
<link href="../style/css/manual-print.css" rel="stylesheet" media="print" type="text/css" />
<title>mod_rewrite － Apache 2.2 中文手册 [金步国]</title>
<script> var _hmt = _hmt || []; (function() { var hm = document.createElement("script"); hm.src = "https://hm.baidu.com/hm.js?d286c55b63a3c54a1e43d10d4c203e75"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(hm, s); })(); </script>
</head>
<body><div id="page-header">
<p class="menu"><a href="index.html">模块索引</a> | <a href="directives.html">指令索引</a> | <a href="../faq/index.html">常见问题</a> | <a href="../glossary.html">词汇表</a> | <a href="../sitemap.html">站点导航</a></p><p class="apache">Apache HTTP Server 版本2.2</p><img alt="" src="../images/feather.gif" /></div>
<div class="up"><a href="index.html"><img title="&lt;-" alt="&lt;-" src="../images/left.gif" /></a></div>
<div id="path"><a href="https://www.apache.org/">Apache</a> &gt; <a href="https://httpd.apache.org/">HTTP Server</a> &gt; <a href="https://httpd.apache.org/docs/">文档</a> &gt; <a href="../index.html">版本2.2</a> &gt; <a href="index.html">模块</a></div>

<div id="translation-info">　　 <a href="../translator_announcement.html#thanks">致谢</a> | 本篇译者：<a href="../../../index.html">金步国</a>(<a href="../../../index.html">作品集</a>) | 本页最后更新：2009年6月8日</div>
<div id="page-content"><div id="preamble"><h1>Apache模块 mod_rewrite</h1>

<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="module">
<tr><th><a href="module-dict.html#Description">说明</a></th><td>一个基于一定规则的实时重写URL请求的引擎</td></tr>
<tr><th><a href="module-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="module-dict.html#ModuleIdentifier">模块名</a></th><td>rewrite_module</td></tr>
<tr><th><a href="module-dict.html#SourceFile">源文件</a></th><td>mod_rewrite.c</td></tr>
<tr><th><a href="module-dict.html#Compatibility">兼容性</a></th><td>仅在 Apache 1.3 及以后的版本中可用</td></tr>
</table>
<h3>概述</h3>

      <p>此模块提供了一个基于正则表达式分析器的重写引擎来实时重写URL请求。它支持每个完整规则可以拥有不限数量的子规则以及附加条件规则的灵活而且强大的URL操作机制。此URL操作可以依赖于各种测试，比如服务器变量、环境变量、HTTP头、时间标记，甚至各种格式的用于匹配URL组成部分的查找数据库。</p>
      <p>此模块可以操作URL的所有部分(包括路径信息部分)，在服务器级的(<code>httpd.conf</code>)和目录级的(<code>.htaccess</code>)配置都有效，还可以生成最终请求字符串。此重写操作的结果可以是内部子处理，也可以是外部请求的转向，甚至还可以是内部代理处理。</p>
	<p>但是，所有这些功能和灵活性带来一个问题，那就是复杂性，因此，不要指望一天之内就能看懂整个模块。</p>
      <p>更多的讨论、细节、示例，请查看详细的<a href="../rewrite/index.html">URL重写文档</a>。</p>
</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="quoting" id="quoting">特殊字符的引用</a></h2>

      <p>在Apache 1.3.20中，<em>TestString</em>和<em>Substitution</em>中的特殊字符可以用前导斜杠(\)来实现转义(即忽略其特殊含义而视之为普通字符)。 比如，<em>Substitution</em>可以用"<code>\$</code>"来包含一个美元符号，以避免mod_rewrite把它视为反向引用。</p>
</div><div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="EnvVar" id="EnvVar">环境变量</a></h2>

      <p>此模块会跟踪两个额外的(非标准)CGI/SSI环境变量，<code>SCRIPT_URL</code>和<code>SCRIPT_URI</code>。他们包含了当前资源的<em>逻辑</em>网络视图，而标准CGI/SSI变量<code>SCRIPT_NAME</code>和<code>SCRIPT_FILENAME</code>包含的是<em>物理</em>系统视图。</p>

      <p>注意：这些变量保持的是<em>其最初被请求时的</em>URI/URL，即在任何重写操作<em>之前</em>的URI/URL。其重要性在于他们是重写操作重写URL到物理路径名的原始依据。</p>

<div class="example"><h3>示例</h3><pre>
SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
SCRIPT_FILENAME=/u/rse/.www/index.html
SCRIPT_URL=/u/rse/
SCRIPT_URI=http://en1.engelschall.com/u/rse/
</pre></div>

</div><div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="section">
<h2><a name="Solutions" id="Solutions">实用方案</a></h2>

    <p>我们提供了<a href="../rewrite/rewrite_guide.html">URL重写指南</a>和<a href="../rewrite/rewrite_guide_advanced.html">高级URL重写指南</a>文档，列举了许多基于URL的问题的实用方案，其中你可以找到真实有用的规则集。</p>

</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteBase" id="RewriteBase">RewriteBase</a> <a name="rewritebase" id="rewritebase">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>设置目录级重写的基准URL</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteBase <em>URL-path</em></code></td></tr>
<tr><th><a href="directive-dict.html#Default">默认值</a></th><td><code>参见使用方法</code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>directory, .htaccess</td></tr>
<tr><th><a href="directive-dict.html#Override">覆盖项</a></th><td>FileInfo</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
</table>
      <p><code class="directive">RewriteBase</code>指令显式地设置了目录级重写的基准URL。在下文中，你将看到<code class="directive"><a href="mod_rewrite.html#rewriterule">RewriteRule</a></code>可以用于目录级的配置文件中(<code>.htaccess</code>)并在局部范围内起作用，即规则实际处理的只是剥离了本地路径前缀的一部分。处理结束后，这个路径会被自动地附着回去。默认值是"<code class="directive">RewriteBase</code> <em>physical-directory-path</em>"。</p>

      <p>在对一个新的URL进行替换时，此模块必须把这个URL重新注入到服务器处理中。为此，它必须知道其对应的URL前缀或者说URL基准。通常，此前缀就是对应的文件路径。<strong>但是，大多数网站URL不是直接对应于其物理文件路径的，因而一般不能做这样的假定! </strong>所以在这种情况下，就必须用<code>RewriteBase</code>指令来指定正确的URL前缀。</p>

<div class="note">如果你的网站服务器URL<strong>不是</strong>与物理文件路径直接对应的，你必须在每个使用<code class="directive"><a href="mod_rewrite.html#rewriterule">RewriteRule</a></code>的<code>.htaccess</code>文件中使用<code class="directive">RewriteBase</code>指令。</div>

        <p>例如，目录级配置文件内容如下：</p>

<div class="example"><pre>
# /abc/def/.htaccess -- /abc/def 目录的配置文件
# 注意：/abc/def 是 /xyz 的物理路径(例如存在一条'Alias /xyz /abc/def'指令)。

RewriteEngine On

# 让服务器知道我们使用的是 /xyz 而不是物理路径 /abc/def
RewriteBase   /xyz

# 重写规则
RewriteRule   ^oldstuff\.html$  newstuff.html
</pre></div>

        <p>上述例子中，对<code>/xyz/oldstuff.html</code>的请求被正确地重写为对物理文件<code>/abc/def/newstuff.html</code>的请求。</p>

<div class="note"><h3>仅供Apache Hacker们参考</h3>
<p>以下列出了内部处理的详细步骤：</p>
<pre>
请求:
  /xyz/oldstuff.html

内部处理过程:
  /xyz/oldstuff.html     -&gt; /abc/def/oldstuff.html  (per-server Alias)
  /abc/def/oldstuff.html -&gt; /abc/def/newstuff.html  (per-dir    RewriteRule)
  /abc/def/newstuff.html -&gt; /xyz/newstuff.html      (per-dir    RewriteBase)
  /xyz/newstuff.html     -&gt; /abc/def/newstuff.html  (per-server Alias)

结果:
  /abc/def/newstuff.html
</pre>
              <p>虽然这个过程看来很繁复，但是由于目录级重写的到来时机已经太晚了，它不得不把这个(重写)请求重新注入到Apache核心中，所以Apache内部确实是这样处理的。但是：它的开销并不象看起来的那样大，因为重新注入完全在Apache服务器内部进行，而且这样的过程在Apache内部也为其他许多操作所使用。所以，你可以充分信任其设计和实现是正确的。</p>
</div>


</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteCond" id="RewriteCond">RewriteCond</a> <a name="rewritecond" id="rewritecond">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>定义重写发生的条件</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code> RewriteCond <em>TestString</em> <em>CondPattern</em> [<em>flags</em>]</code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host, directory, .htaccess</td></tr>
<tr><th><a href="directive-dict.html#Override">覆盖项</a></th><td>FileInfo</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
</table>
      <p><code class="directive">RewriteCond</code>指令定义了规则生效的条件，即在一个<code class="directive"><a href="mod_rewrite.html#rewriterule">RewriteRule</a></code>指令之前可以有一个或多个<code class="directive">RewriteCond</code>指令。条件之后的重写规则仅在当前URI与<em>Pattern</em>匹配<strong>并且</strong>满足此处的条件(<em>TestString</em>能够与<em>CondPattern</em>匹配)时才会起作用。</p>

      <p><em>TestString</em>是一个纯文本的字符串，但是还可以包含下列可扩展的成分：</p>

      <ul>
        <li>
          <strong>RewriteRule反向引用</strong> ，引用方法是：

          <p class="indent">
            <strong><code>$N</code></strong>
          </p>(0 &lt;= N &lt;= 9)引用当前(带有若干<code>RewriteRule</code>指令的)<code>RewriteCond</code>中的与<em>Pattern</em>匹配的分组成分(圆括号!)。</li>

        <li>
          <strong>RewriteCond反向引用</strong> ，引用方法是：
          <p class="indent">
            <strong><code>%N</code></strong>
          </p>(1 &lt;= N &lt;= 9)引用当前若干<code>RewriteCond</code>条件中最后符合的条件中的分组成分(圆括号!)。</li>

        <li>
          <strong>RewriteMap扩展</strong> ，引用方法是：
          <p class="indent">
            <strong><code>${mapname:key|default}</code></strong>
          </p>细节请参见<a href="mod_rewrite.html#mapfunc">RewriteMap 指令</a>。
        </li>

        <li>
          <strong>服务器变量</strong> ，引用方法是：
          <p class="indent">
            <strong><code>%{</code><em>NAME_OF_VARIABLE</em><code>}</code></strong>
          </p><em>NAME_OF_VARIABLE</em>可以是下表列出的字符串之一：
          <table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA">
<tr><th>HTTP头</th><th>连接与请求</th><th /></tr>
<tr><td>
		 HTTP_USER_AGENT<br />
                 HTTP_REFERER<br />
                 HTTP_COOKIE<br />
                 HTTP_FORWARDED<br />
                 HTTP_HOST<br />
                 HTTP_PROXY_CONNECTION<br />
                 HTTP_ACCEPT<br />
              </td><td>
                 REMOTE_ADDR<br />
                 REMOTE_HOST<br />
                 REMOTE_PORT<br />
                 REMOTE_USER<br />
                 REMOTE_IDENT<br />
                 REQUEST_METHOD<br />
                 SCRIPT_FILENAME<br />
                 PATH_INFO<br />
                 QUERY_STRING<br />
                 AUTH_TYPE<br />
              </td><td /></tr>
<tr><th>服务器自身</th><th>日期和时间</th><th>其它</th></tr>
<tr><td>
	         DOCUMENT_ROOT<br />
                 SERVER_ADMIN<br />
                 SERVER_NAME<br />
                 SERVER_ADDR<br />
                 SERVER_PORT<br />
                 SERVER_PROTOCOL<br />
                 SERVER_SOFTWARE<br />
              </td><td>
                 TIME_YEAR<br />
                 TIME_MON<br />
                 TIME_DAY<br />
                 TIME_HOUR<br />
                 TIME_MIN<br />
                 TIME_SEC<br />
                 TIME_WDAY<br />
                 TIME<br />
              </td><td>
                 API_VERSION<br />
                 THE_REQUEST<br />
                 REQUEST_URI<br />
                 REQUEST_FILENAME<br />
                 IS_SUBREQ<br />
                 HTTPS<br />
              </td></tr>
</table>

                <p>这些变量都对应于类似命名的HTTP MIME头、Apache服务器的C变量、Unix系统中的<code>struct tm</code>字段，其中的大多数在其他的手册或者CGI规范中都有说明。 其中为mod_rewrite所特有的变量如下：</p>
	<div class="note">
                <dl>
                  <dt><code>IS_SUBREQ</code></dt>

                  <dd>如果正在处理的请求是一个子请求，它将包含字符串"true"，否则就是"false"。模块为了解析URI中的附加文件，可能会产生子请求。</dd>

                  <dt><code>API_VERSION</code></dt>

                  <dd>这是正在使用中的Apache模块API(服务器和模块之间内部接口)的版本， 其定义位于include/ap_mmn.h中。此模块API版本对应于正在使用的Apache的版本(比如在Apache 1.3.14的发行版中这个值是19990320:10)。 通常，对它感兴趣的是模块的开发者。</dd>

                  <dt><code>THE_REQUEST</code></dt>

                  <dd>这是由浏览器发送的完整的HTTP请求行(比如："<code>GET /index.html HTTP/1.1</code>")。它不包含任何浏览器发送的其它头信息。</dd>

                  <dt><code>REQUEST_URI</code></dt>

                  <dd>这是在HTTP请求行中所请求的资源(比如上述例子中的"/index.html")。</dd>

                  <dt><code>REQUEST_FILENAME</code></dt>

                  <dd>这是与请求相匹配的完整的本地文件系统的文件路径名。</dd>

                  <dt><code>HTTPS</code></dt>

                  <dd>如果连接使用了SSL/TLS，它将包含字符串"on"，否则就是"off"(无论<code class="module"><a href="mod_ssl.html">mod_ssl</a></code>是否已经加载，该变量都可以安全的使用)。</dd>

                </dl>
</div>
        </li>
      </ul>

      <p>其它注意事项：</p>

      <ol>
        <li>SCRIPT_FILENAME和REQUEST_FILENAME包含的值是相同的――即Apache服务器内部的<code>request_rec</code>结构中的<code>filename</code>字段。 第一个就是大家都知道的CGI变量名，而第二个则是REQUEST_URI(<code>request_rec</code>结构中的<code>uri</code>字段)的一个副本。</li>

        <li>特殊形式：<code>%{ENV:variable}</code> ，其中的<em>variable</em>可以是任意环境变量。它是通过查找Apache内部结构或者(如果没找到的话)由Apache服务器进程通过<code>getenv()</code>得到的。</li>

        <li>特殊形式：<code>%{SSL:variable}</code> ，其中的<em>variable</em>可以是一个<a href="mod_ssl.html#envvars">SSL环境变量</a>的名字，无论<code class="module"><a href="mod_ssl.html">mod_ssl</a></code>模块是否已经加载都可以使用(未加载时为空字符串)。比如：<code>%{SSL:SSL_CIPHER_USEKEYSIZE}</code>将会被替换为<code>128</code>。</li>

        <li>特殊形式：<code>%{HTTP:header}</code> ，其中的<em>header</em>可以是任意HTTP MIME头的名称。它总是可以通过查找HTTP请求而得到。比如：<code>%{HTTP:Proxy-Connection}</code>将被替换为<code>Proxy-Connection:</code>HTTP头的值。</li>

        <li>预设形式：<code>%{LA-U:variable}</code> ，<em>variable</em>的最终值在执行一个内部(基于URL的)子请求后确定。 当需要使用一个目前未知但是会在之后的过程中设置的变量的时候，就可以使用这个方法。
		<p>例如，需要在服务器级配置(<code>httpd.conf</code>文件)中根据<code>REMOTE_USER</code>变量进行重写， 就必须使用<code>%{LA-U:REMOTE_USER}</code>。因为此变量是由URL重写(mod_rewrite)步骤<em>之后</em>的认证步骤设置的。 但是另一方面，因为mod_rewrite是通过API修正步骤来实现目录级(<code>.htaccess</code>文件)配置的， 而认证步骤<em>先于</em>API修正步骤，所以可以用<code>%{REMOTE_USER}</code>。</p>
		</li>

        <li>预设形式：<code>%{LA-F:variable}</code> ，<em>variable</em>的最终值在执行一个内部(基于文件名的)子请求后确定。 大多数情况下和上述的LA-U是相同的。</li>
      </ol>

      <p><em>CondPattern</em>是条件模式，即一个应用于当前<em>TestString</em>实例的正则表达式。<em>TestString</em>将被首先计算，然后再与<em>CondPattern</em>匹配。</p>

      <p><strong>注意：</strong><em>CondPattern</em>是一个<em>perl兼容的正则表达式</em>，但是还有若干增补：</p>

      <ol>
        <li>可以在<em>CondPattern</em>串的开头使用'<code>!</code>'(惊叹号)来指定<strong>不匹配</strong>。</li>

        <li><em>CondPatterns</em>有若干特殊的变种。除了正则表达式的标准用法，还有下列用法：
          <ul>
            <li>'<strong>&lt;CondPattern</strong>'(词典顺序的小于)<br />
            将<em>CondPattern</em>视为纯字符串，与<em>TestString</em>按词典顺序进行比较。如果<em>TestString</em>小于<em>CondPattern</em>则为真。</li>

            <li>'<strong>&gt;CondPattern</strong>'(词典顺序的大于)<br />
            将<em>CondPattern</em>视为纯字符串，与<em>TestString</em>按词典顺序进行比较。如果<em>TestString</em>大于<em>CondPattern</em>则为真。</li>

            <li>'<strong>=CondPattern</strong>'(词典顺序的等于)<br />
            将<em>CondPattern</em>视为纯字符串，与<em>TestString</em>按词典顺序进行比较。如果<em>TestString</em>等于<em>CondPattern</em>(两个字符串逐个字符地完全相等)则为真。如果<em>CondPattern</em>是<code>""</code>(两个双引号)，则<em>TestString</em>将与空字符串进行比较。</li>

            <li>'<strong>-d</strong>'(目录)<br />
             将<em>TestString</em>视为一个路径名并测试它是否为一个存在的目录。</li>

            <li>'<strong>-f</strong>'(常规文件)<br />
             将<em>TestString</em>视为一个路径名并测试它是否为一个存在的常规文件。</li>

            <li>'<strong>-s</strong>'(非空的常规文件)<br />
            将<em>TestString</em>视为一个路径名并测试它是否为一个存在的、尺寸大于0的常规文件。</li>

            <li>'<strong>-l</strong>'(符号连接)<br />
            将<em>TestString</em>视为一个路径名并测试它是否为一个存在的符号连接。</li>

            <li>'<strong>-x</strong>'(可执行)<br />
            将<em>TestString</em>视为一个路径名并测试它是否为一个存在的、具有可执行权限的文件。该权限由操作系统检测。</li>

            <li>'<strong>-F</strong>'(对子请求存在的文件)<br />
            检查<em>TestString</em>是否为一个有效的文件，而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查，由于会降低服务器的性能，所以请谨慎使用！</li>

            <li>'<strong>-U</strong>'(对子请求存在的URL)<br />
            检查<em>TestString</em>是否为一个有效的URL，而且可以在服务器当前的访问控制配置下被访问。它使用一个内部子请求来做检查，由于会降低服务器的性能，所以请谨慎使用！</li>
          </ul>

<div class="note"><h3>注意</h3>所有这些测试都可以用惊叹号作前缀('!')以实现测试条件的反转。</div>
        </li>

	<li>还可以在<em>CondPattern</em>之后追加特殊的标记<strong><code>[<em>flags</em>]</code></strong>作为<code>RewriteCond</code>指令的第三个参数。<em>flags</em>是一个以逗号分隔的以下标记的列表：

      <ul>
        <li>'<strong><code>nocase|NC</code></strong>'(忽略大小写)<br />
        它使测试忽略大小写，扩展后的<em>TestString</em>和<em>CondPattern</em>中'A-Z' 和'a-z'是没有区别的。此标记仅用于<em>TestString</em>和<em>CondPattern</em>的比较，而对文件系统和子请求的检查不起作用。</li>

        <li>'<strong><code>ornext|OR</code></strong>'(或下一条件)<br />
          它以OR方式组合若干规则的条件，而不是隐含的AND。典型的例子如下：
<div class="example"><pre>
RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host3.*
RewriteRule ... 针对这3个主机的规则集 ...
</pre></div>
如果不用这个标记，你就必须要书写三次条件/规则对。
        </li>
      </ul>
      </li>
     </ol>

      <p><strong>举例</strong></p>

       <p>如果要按请求头中的"<code>User-Agent:</code>"重写一个站点的主页，可以这样写：</p>

<div class="example"><pre>
RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]
</pre></div>
        <p>解释：如果你使用的浏览器识别标志是'Mozilla'，则你将得到内容最大化的主页(含有Frames等等)。如果你使用的是(基于终端的)Lynx，则你得到的是内容最小化的主页(不含table等等)。如果上述条件都不满足(使用的是其他浏览器)，则你得到的是一个标准的主页。</p>

</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteEngine" id="RewriteEngine">RewriteEngine</a> <a name="rewriteengine" id="rewriteengine">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>打开或关闭运行时的重写引擎</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteEngine on|off</code></td></tr>
<tr><th><a href="directive-dict.html#Default">默认值</a></th><td><code>RewriteEngine off</code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host, directory, .htaccess</td></tr>
<tr><th><a href="directive-dict.html#Override">覆盖项</a></th><td>FileInfo</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
</table>

      <p><code class="directive">RewriteEngine</code>指令打开或关闭运行时的重写引擎。如果设置为<code>off</code>，则此模块在运行时不执行任何重写操作， 同时也不更新<code>SCRIPT_URx</code>环境变量。</p>

      <p>使用该指令可以使此模块无效，而无须注释所有的<code class="directive"><a href="mod_rewrite.html#rewriterule">RewriteRule</a></code>指令！</p>

      <p>注意：默认情况下，重写配置是不可继承的，也就是必须在每个需要使用重写引擎的虚拟主机中设置一个<code>RewriteEngine on</code>指令。</p>

</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteLock" id="RewriteLock">RewriteLock</a> <a name="rewritelock" id="rewritelock">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>设置<code class="directive"><a href="mod_rewrite.html#rewritemap">RewriteMap</a></code>同步所使用的锁文件名</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteLock <em>file-path</em></code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
</table>
      <p>此指令设置mod_rewrite为了和<code class="directive"><a href="mod_rewrite.html#rewritemap">RewriteMap</a></code><em>程序</em>通讯而使用的同步锁文件的名称。 在需要使用重写映射表程序(rewriting map-program)时，它必须是一个本地路径(而不能是一个NFS挂接设备)。对其他类型的重写映射表(rewriting map)，则无此要求。</p>

</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteLog" id="RewriteLog">RewriteLog</a> <a name="rewritelog" id="rewritelog">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>设置重写引擎日志的文件名</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteLog <em>file-path</em></code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
</table>
      <p><code class="directive">RewriteLog</code>指令设置用于记录所有重写操作的日志文件的名称。如果此文件名不以斜杠('<code>/</code>')开头，则它是相对于<em>Server Root</em>的，此指令应该在每个服务器级别的配置中仅仅出现一次。</p>

<div class="note">如果要关闭对重写操作的记录，不推荐将<em>Filename</em>设为<code>/dev/null</code> ，因为，虽然重写引擎不能输出记录了，但仍会在内部建立这个日志文件，<strong>这样会使服务器速度降低，而且对管理员毫无益处！</strong>要关闭日志，可以删除或注解<code class="directive">RewriteLog</code>指令， 或者使用"<code>RewriteLogLevel 0</code>"的设置</div>

<div class="note"><h3>安全</h3>
参见<a href="../misc/security_tips.html">安全方面的提示</a>文档，其中讲述了为什么如果存放日志的目录对除了启动服务器以外的用户是可写的会带来安全隐患。</div>

<div class="example"><h3>示例</h3><p><code>
RewriteLog "/usr/local/var/apache/logs/rewrite.log"
</code></p></div>


</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteLogLevel" id="RewriteLogLevel">RewriteLogLevel</a> <a name="rewriteloglevel" id="rewriteloglevel">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>设置重写日志的详细程度</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteLogLevel <em>Level</em></code></td></tr>
<tr><th><a href="directive-dict.html#Default">默认值</a></th><td><code>RewriteLogLevel 0</code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
</table>
      <p><code class="directive">RewriteLogLevel</code>指令设置重写引擎日志的详细程度的级别。0(默认级别)意味着不记录，而9或更大的值意味着记录所有操作。</p>

      <p>要关闭重写引擎日志，可以简单地将<em>Level</em>设为0，以关闭所有重写操作的记录。</p>

<div class="note">较高的<em>Level</em>值会使Apache服务器速度急剧下降！大于2的<em>Level</em>值只用于调试目的！</div>

<div class="example"><h3>示例</h3><p><code>
RewriteLogLevel 3
</code></p></div>


</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteMap" id="RewriteMap">RewriteMap</a> <a name="rewritemap" id="rewritemap">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>定义用于关键词查找的映射函数</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteMap <em>MapName</em> <em>MapType</em>:<em>MapSource</em></code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
<tr><th><a href="directive-dict.html#Compatibility">兼容性</a></th><td>Apache 2.0.41 及以后的版本中可以使用不同的dbm类型</td></tr>
</table>
      <p><code class="directive">RewriteMap</code>指令定义了一个<em>映射表</em>(Rewriting Map)，映射函数将使用该表来查找关键字然后插入/替换字段。此查找操作的源可以是多种类型。</p>

      <p><a id="mapfunc" name="mapfunc"><em>MapName</em></a>是映射表的名称，指定了一个映射函数，用于重写规则的字符串替换，它可以是下列形式之一：</p>

      <p class="indent">
        <strong><code>${</code><em>MapName</em><code>:</code><em>LookupKey</em><code>}</code><br />
         <code>${</code><em>MapName</em><code>:</code><em>LookupKey</em><code>|</code><em>DefaultValue</em><code>}</code></strong>
      </p>

      <p>如果使用了这样的形式，则会在<em>MapName</em>中查找关键词<em>LookupKey</em>。如果找到了，则被替换成<em>SubstValue</em>； 如果没有找到，则被替换成<em>DefaultValue</em>，如果没有指定<em>DefaultValue</em>，则被替换成空字符串。</p>

      <p>例如，你可能定义这样一个<code class="directive">RewriteMap</code>：</p>
      <div class="example"><p><code>
      RewriteMap examplemap txt:/path/to/file/map.txt
      </code></p></div>

      <p>然后你就可以像下面这样在<code class="directive">RewriteRule</code>中使用该映射：</p>
      <div class="example"><p><code>
      RewriteRule ^/ex/(.*) ${examplemap:$1}
      </code></p></div>

      <p>可以使用下列<em>MapType</em>和<em>MapSource</em>的组合：</p>

      <ul>
        <li>
          <strong>标准纯文本</strong><br />
           MapType: <code>txt</code>, MapSource: 有效的Unix文件系统文件名

          <p>这是重写映射表的标准形式。<em>MapSource</em>是一个纯文本文件，包含空行、注释行(以字符'#'打头)，以及每行一个的替换对，如下所示：</p>

          <p class="indent"><strong><em>MatchingKey</em> <em>SubstValue</em></strong></p>

<div class="example"><h3>例子</h3><pre>##  map.txt -- rewriting map

Ralf.S.Engelschall    rse   # Bastard Operator From Hell
Mr.Joe.Average        joe   # Mr. Average
</pre></div>

<div class="example"><p><code>
RewriteMap real-to-user txt:/path/to/file/map.txt
</code></p></div>
        </li>

        <li>
          <strong>随机纯文本</strong><br />
           MapType: <code>rnd</code>, MapSource: 有效的Unix文件系统文件名

          <p>这个与上述的标准纯文本很相似，但它有一个特殊的后处理特性：查找完毕后，会解析其中包含的"<code>|</code>"符号(含义为"或")。 也就是说，会随机地选择其中之一作为返回值。虽然这看似毫无意义，但设计它的意图是在一个查找值是服务器名称的反向代理环境中实现负载平衡。</p>
          <p>例子</p>
<div class="example"><h3>映射文件</h3><pre>##  map.txt -- rewriting map

static   www1|www2|www3|www4
dynamic  www5|www6
</pre></div>

<div class="example"><h3>配置指令</h3><p><code>
RewriteMap servers rnd:/path/to/file/map.txt<br />
<br />
RewriteRule ^/(.*\.(png|gif|jpg)) http://${servers:static}/$1 [NC,P,L]<br />
RewriteRule ^/(.*) http://${servers:dynamic}/$1 [P,L]</code></p>
</div>
        </li>

        <li>
          <strong>散列文件</strong><br />
		  MapType: <code>dbm[=<em>type</em>]</code>, MapSource: 有效的Unix文件系统文件名

          <p>这里的源是一个二进制格式的DBM文件，包含了与<em>纯文本</em>相同的内容，但是因为它有优化了的特殊表现形式，使它的查找速度明显快得多。 此<em>type</em>可以是sdbm, gdbm, ndbm, db(由<a href="../install.html#dbm">编译时配置</a>决定)。如果省略<em>type</em>，则使用编译时选择的缺省值。 你可以使用任何DBM工具或者下列Perl脚本来创建这个文件，但必须保证DBM的类型正确。建立NDBM文件的例子如下：</p>

<div class="example"><pre>
#!/path/to/bin/perl
##
##  txt2dbm -- 将 txt 映射表转换为 dbm 格式
##

use NDBM_File;
use Fcntl;

($txtmap, $dbmmap) = @ARGV;

open(TXT, "&lt;$txtmap") or die "Couldn't open $txtmap!\n";
tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644)
  or die "Couldn't create $dbmmap!\n";

while (&lt;TXT&gt;) {
  next if (/^\s*#/ or /^\s*$/);
  $DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/);
}

untie %DB;
close(TXT);
</pre></div>

<div class="example"><p><code>
$ txt2dbm map.txt map.db
</code></p></div>
        </li>

        <li>
          <strong>内部函数</strong><br />
           MapType: <code>int</code>, MapSource: Apache内部函数

          <p>这里的源是一个Apache的内部函数。目前，还不能由你自己建立，只能使用下列已经存在的函数：</p>

          <ul>
            <li><strong>toupper</strong>:<br />
            转换查找关键词为大写</li>

            <li><strong>tolower</strong>:<br />
            转换查找关键词为小写</li>

            <li><strong>escape</strong>:<br />
            转换查找关键词中的特殊字符为十六进制编码</li>

            <li><strong>unescape</strong>:<br />
            转换查找关键词中的十六进制编码为特殊字符</li>
          </ul>
        </li>

        <li>
          <strong>外部的重写程序</strong><br />
           MapType: <code>prg</code>, MapSource: 有效的Unix文件系统文件名

          <p>这里的源是一个程序，而不是一个映射表文件。程序设计语言可以随意选择，但最终结果必须是可执行的(或者是目标代码，或者是首行为'<code>#!/path/to/interpreter</code>'的脚本)。</p>

         <p>此程序仅在Apache服务器启动时启动一次，随后通过<code>stdin</code>和<code>stdout</code>文件句柄与重写引擎交互。 对每个映射函数的查找操作，它从<code>stdin</code>接收以回车结束的查找关键词，然后把查找的结果以回车结束反馈到<code>stdout</code>，如果查找失败，则返回四个字符的字符串"NULL"(对给定的关键词没有对应的值)。此程序的最简单形式是一个1:1的映射(即：key == value)，例如：</p>

<div class="example"><pre>
#!/usr/bin/perl
$| = 1;
while (&lt;STDIN&gt;) {
    # ...在这里放置转换和查找...
    print $_;
}
</pre></div>

          <p>但是必须注意：</p>

          <ol>
            <li>"<em>简单就是美</em>"(KISS: Keep it simple, stupid!)。此程序的崩溃会直接导致Apache服务器的崩溃。</li>

            <li>绝不要对<code>stdout</code>做I/O缓冲(一个常见的错误)，它会导致死循环！所以上述例子中才会使用"<code>$|=1</code>"来预防。</li>

            <li>使用<code class="directive"><a href="mod_rewrite.html#rewritelock">RewriteLock</a></code>指令定义一个锁文件，用于同步mod_rewrite和此程序之间的通讯。默认是没有同步操作的。</li>
          </ol>
        </li>
      </ul>
      <p><code class="directive">RewriteMap</code>指令可以多次出现。对每个映射函数都可以使用一个<code class="directive">RewriteMap</code>指令来定义其重写映射表。虽然不能在目录上下文(per-directory context)中<strong>定义</strong>映射表，但是完全可以在其中<strong>使用</strong>映射表。</p>

<div class="note"><h3>注意</h3>
对于纯文本和DBM格式的文件，已经查找过的关键词会被缓存在内核中，直到映射表的<code>mtime</code>改变了或者服务器重启了。这样，你可以把<strong>每个</strong>请求都会用到的映射函数放在规则中，这是没有问题的，因为外部查找只进行一次。
</div>


</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteOptions" id="RewriteOptions">RewriteOptions</a> <a name="rewriteoptions" id="rewriteoptions">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>为重写引擎设置一些特殊的选项</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteOptions <var>Options</var></code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host, directory, .htaccess</td></tr>
<tr><th><a href="directive-dict.html#Override">覆盖项</a></th><td>FileInfo</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
<tr><th><a href="directive-dict.html#Compatibility">兼容性</a></th><td><code>MaxRedirects</code>在2.1及以后的版本中已经不可用</td></tr>
</table>

      <p><code class="directive">RewriteOptions</code>指令为当前服务器级和目录级的配置设置一些选项。<em>Option</em>当前仅可以是如下值：</p>

      <dl>
      <dt><code>inherit</code></dt>
      <dd>此值强制当前配置继承其父配置。在虚拟主机级配置中，它意味着主服务器的映射表、条件和规则可以被继承。在目录级配置中，它意味着其父目录的<code>.htaccess</code>中的条件和规则可以被继承。</dd>
      </dl>
</div>
<div class="top"><a href="mod_rewrite.html#page-header"><img alt="top" src="../images/up.gif" /></a></div>
<div class="directive-section"><h2><a name="RewriteRule" id="RewriteRule">RewriteRule</a> <a name="rewriterule" id="rewriterule">指令</a></h2>
<table border="1" cellpadding="0" cellspacing="0" bordercolor="#AAAAAA" class="directive">
<tr><th><a href="directive-dict.html#Description">说明</a></th><td>为重写引擎定义重写规则</td></tr>
<tr><th><a href="directive-dict.html#Syntax">语法</a></th><td><code>RewriteRule <em>Pattern</em> <em>Substitution</em> [<em>flags</em>]</code></td></tr>
<tr><th><a href="directive-dict.html#Context">作用域</a></th><td>server config, virtual host, directory, .htaccess</td></tr>
<tr><th><a href="directive-dict.html#Override">覆盖项</a></th><td>FileInfo</td></tr>
<tr><th><a href="directive-dict.html#Status">状态</a></th><td>扩展(E)</td></tr>
<tr><th><a href="directive-dict.html#Module">模块</a></th><td>mod_rewrite</td></tr>
<tr><th><a href="directive-dict.html#Compatibility">兼容性</a></th><td>cookie-flag在Apache 2.0.40及以后的版本中可用</td></tr>
</table>
      <p><code class="directive">RewriteRule</code>指令是重写引擎的根本。此指令可以多次使用。每个指令定义一个简单的重写规则。这些规则的定义顺序尤为重要――在运行时，规则是按这个顺序逐一生效的。</p>

      <p><a id="patterns" name="patterns"><em>Pattern</em></a>是一个作用于当前URL的perl兼容的<a id="regexp" name="regexp">正则表达式</a>。"当前URL"是指该规则生效时刻的URL的值。它可能与被请求的URL截然不同，因为其他规则可能在此之前已经发生匹配并对它做了改动。</p>

      <p><a class="glossarylink" href="../glossary.html#regex" title="see glossary">正则表达式</a>的一些用法示例：</p>

<div class="note"><pre>
<strong>文本</strong>
  <strong><code>.</code></strong>           任意一个单字符
  <strong><code>[</code></strong>chars<strong><code>]</code></strong>     字符类: "chars"中的任意一个字符
  <strong><code>[^</code></strong>chars<strong><code>]</code></strong>    字符类: 不在"chars"中的字符
  text1<strong><code>|</code></strong>text2 选择: text1 或 text2

<strong>量词</strong>
  <strong><code>?</code></strong>           前面的字符出现 0 或 1 次
  <strong><code>*</code></strong>           前面的字符出现 0 或 N 次(N &gt; 0)
  <strong><code>+</code></strong>           前面的字符出现 1 或 N 次(N &gt; 1)

<strong>分组</strong>
  <strong><code>(</code></strong>text<strong><code>)</code></strong>      text 组
              (常用于设置一个选择的边界，或用于生成后引用：
               在RewriteRule中可以用 <code>$</code><strong>N</strong> 引用第<strong>N</strong>个分组)

<strong>锚</strong>
  <strong><code>^</code></strong>           锚定到行首
  <strong><code>$</code></strong>           锚定到行尾

<strong>转义</strong>
  <strong><code>\</code></strong>c          对给定的字符c进行转义
              (比如对"<code>.[]()</code>"进行转义，等等)
</pre></div>

      <p>更多有关正则表达式的资料请参见perl正则表达式手册页("<a href="http://www.perldoc.com/perl5.8.8/pod/perlre.html">perldoc perlre</a>")。另外，在mod_rewrite中，还可以使用否字符('<code>!</code>')前缀实现反转。比如："<em>如果当前URL<strong>不</strong>与模式相匹配</em>"它用于使用否定式匹配模式较容易描述的某些情况，或者作为最后一条规则。</p>

<div class="note"><h3>注意</h3>
使用否字符以反转匹配模式时，匹配模式中不能使用分组的通配成分。由于模式不匹配而使分组的内容是空的，所以它是不可能实现的。 因此，如果使用了否定式匹配模式，那么后继的字符串中就不能使用<code>$N</code>
</div>

      <p>重写规则中的<a id="rhs" name="rhs"><em>Substitution</em></a>是当原始URL与<em>Pattern</em>相匹配时，用来替代(或替换)的字符串。除了纯文本，还可以包含：</p>

      <ol>
        <li>对<em>Pattern</em>的反向引用(<code>$N</code>)</li>

        <li>对最后匹配的<em>RewriteCond</em>的反向引用(<code>%N</code>)</li>

        <li>规则条件测试字符串(<code>%{VARNAME}</code>)中的服务器变量</li>

        <li><a href="mod_rewrite.html#mapfunc">映射函数</a>调用(<code>${mapname:key|default}</code>)</li>
      </ol>
      <p>反向引用的<code>$</code><strong>N</strong>(<strong>N</strong>=0..9)是指用<em>Pattern</em>匹配的第<strong>N</strong>组的内容去替换URL。服务器变量与<code>RewriteCond</code>指令的<em>TestString</em>相同。映射函数由<code>RewriteMap</code>指令决定，其说明也参见该指令。这三种类型变量按上面列表中的顺序被展开。</p>

      <p>如上所述，所有的重写规则都是按配置文件中的定义顺序作用于<em>Substitution</em>的。URL被<em>Substitution</em><strong>完全替换</strong>，并继续处理直到所有规则处理完毕，除非用<code><strong>L</strong></code>标记显式地终结(见下文)。</p>

      <p>'<code>-</code>'是一个特殊的替换串，意思是<strong>不替换</strong>。它可以用于<strong>仅仅</strong>匹配某些URL而无须替换的情况，比如，在发生替换前，允许以<strong>C</strong>(chain)标记连接的多个匹配模式同时起作用。</p>


      <p>此外，在<em>Substitution</em>之后还可以追加<strong><code>[</code><em>flags</em><code>]</code></strong>标记作为<code>RewriteRule</code>指令的第三个参数。<em>Flags</em>是一个包含以逗号分隔的下列标记的列表：</p>

      <ul>
        <li>'<strong><code>chain|C</code></strong>'(链接下一规则)<br />
         此标记使当前规则与下一个规则相链接。它产生这样的效果：如果一个规则被匹配，则继续处理其后继规则，也就是这个标记不起作用；如果该规则<strong>不</strong>被匹配，则其后继规则将被跳过。比如，在一个目录级规则中执行一个外部重定向时，你可能需要删除"<code>.www</code>"(此处不应该出现"<code>.www</code>")。</li>

        <li>'<strong><code>cookie|CO=</code></strong><em>NAME</em>:<em>VAL</em>:<em>domain</em>[:<em>lifetime</em>[:<em>path</em>]]'(设置cookie)<br />
        在客户端设置一个cookie。cookie的名称是<em>NAME</em>，值是<em>VAL</em>。<em>domain</em>是该cookie的域，比如'.apache.org'，可选的<em>lifetime</em>是cookie的有效期(分钟)，可选的<em>path</em>是cookie的路径。</li>

        <li>'<strong><code>env|E=</code></strong><em>VAR</em>:<em>VAL</em>'(设置环境变量)<br />
        此标记将环境变量<em>VAR</em>的值为<em>VAL</em>，<em>VAL</em>可以包含可扩展的正则表达式反向引用(<code>$N</code>和<code>%N</code>)。此标记可以多次使用以设置多个变量。这些变量可以在其后许多情况下被间接引用，通常是在XSSI(<code>&lt;!--#echo var="VAR"--&gt;</code>)或CGI(<code>$ENV{'VAR'}</code>)中，也可以在后继的<code class="directive">RewriteCond</code>指令的<em>CondPattern</em>参数中通过<code>%{ENV:VAR}</code>引用。使用它可以记住从URL中剥离的信息。</li>

        <li>'<strong><code>forbidden|F</code></strong>'(强制禁止URL)<br />
        强制禁止当前URL，也就是立即反馈一个HTTP响应码403(被禁止的)。使用这个标记，可以链接若干个RewriteConds来有条件地阻塞某些URL。</li>

        <li>'<strong><code>gone|G</code></strong>'(强制废弃URL)<br />
        强制当前URL为已废弃，也就是立即反馈一个HTTP响应码410(已废弃的)。使用这个标记，可以标明页面已经被废弃而不存在了。</li>

        <li>'<strong><code>handler|H</code></strong>=<em>Content-handler</em>'(强制指定内容处理器)<br />
        强自制定目标文件的内容处理器为<em>Content-handler</em>。例如，用来模拟<code class="module"><a href="mod_alias.html">mod_alias</a></code>模块的<code class="directive"><a href="mod_alias.html#scriptalias">ScriptAlias</a></code>指令，以强制映射文件夹内的所有文件都由"<code>cgi-script</code>"处理器处理。</li>

        <li>'<strong><code>last|L</code></strong>'(结尾规则)<br />
        立即停止重写操作，并不再应用其他重写规则。它对应于Perl中的<code>last</code>命令或C语言中的<code>break</code>命令。这个标记用于阻止当前已被重写的URL被后继规则再次重写。例如，使用它可以重写根路径的URL('<code>/</code>')为实际存在的URL(比如：'<code>/e/www/</code>')。</li>

        <li>'<strong><code>next|N</code></strong>'(从头再来)<br />
        重新执行重写操作(从第一个规则重新开始)。此时再次进行处理的URL已经不是原始的URL了，而是经最后一个重写规则处理过的URL。它对应于Perl中的<code>next</code>命令或C语言中的<code>continue</code>命令。此标记可以重新开始重写操作(立即回到循环的开头)。<strong>但是要小心，不要制造死循环！</strong></li>

        <li>'<strong><code>nocase|NC</code></strong>'(忽略大小写)<br />
        它使<em>Pattern</em>忽略大小写，也就是在<em>Pattern</em>与当前URL匹配时，'A-Z'和'a-z'没有区别。</li>

        <li>'<strong><code>noescape|NE</code></strong>'(在输出中不对URI进行转义)<br />
         此标记阻止mod_rewrite对重写结果应用常规的URI转义规则。 一般情况下，特殊字符('%', '$', ';'等)会被转义为等值的十六进制编码('%25', '%24', '%3B'等)。此标记可以阻止这样的转义，以允许百分号等符号出现在输出中，比如：
<div class="example"><p><code>
    RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]
</code></p></div>
          可以使'<code>/foo/zed</code>转向到一个安全的请求'<code>/bar?arg=P1=zed</code>'。</li>

        <li>'<strong><code>nosubreq|NS</code></strong>'(不对内部子请求进行处理)<br />
        在当前请求是一个内部子请求时，此标记强制重写引擎跳过该重写规则。比如，在<code class="module"><a href="mod_include.html">mod_include</a></code>试图搜索目录默认文件(<code>index.xxx</code>)时，Apache会在内部产生子请求。对于子请求，重写规则不一定有用，而且如果整个规则集都起作用，它甚至可能会引发错误。所以，可以用这个标记来排除某些规则。<br />使用原则：如果你为URL添加了CGI脚本前缀，以强制它们由CGI脚本处理，但对子请求处理的出错率(或者资源开销)很高，在这种情况下，可以使用这个标记。</li>

        <li>'<strong><code>proxy|P</code></strong>'(强制为代理)<br />
         此标记使替换成分被内部地强制作为代理请求发送，并立即中断重写处理，然后把处理移交给<a href="mod_proxy.html">mod_proxy</a>模块。你必须确保此替换串是一个能够被<a href="mod_proxy.html">mod_proxy</a>处理的有效URI(比如以<code>http://</code><em>hostname</em>开头)，否则将得到一个代理模块返回的错误。使用这个标记，可以把某些远程成分映射到本地服务器域名空间，从而增强了<a href="mod_proxy.html#proxypass">ProxyPass</a>指令的功能。
          <p>注意：要使用这个功能，必须已经启用了<code class="module"><a href="mod_proxy.html">mod_proxy</a></code>模块。</p>
        </li>

        <li>'<strong><code>passthrough|PT</code></strong>'(移交给下一个处理器)<br />
         此标记强制重写引擎将内部<code>request_rec</code>结构中的<code>uri</code>字段设置为<code>filename</code>字段的值，这个小小的修改使得<code>RewriteRule</code>指令的输出能够被(从URI转换到文件名的)<code>Alias</code>, <code>ScriptAlias</code>, <code>Redirect</code>等指令进行后续处理[原文：This flag is just a hack to enable post-processing of the output of <code>RewriteRule</code> directives, using <code>Alias</code>, <code>ScriptAlias</code>, <code>Redirect</code>, and other directives from various URI-to-filename translators.]。举一个能说明其含义的例子： 如果要将<code>/abc</code>重写为<code>/def</code>， 然后再使用<code class="module"><a href="mod_alias.html">mod_alias</a></code>将<code>/def</code>转换为<code>/ghi</code>，可以这样：
<div class="example"><p><code>
    RewriteRule ^/abc(.*)  /def$1 [PT]<br />
    Alias       /def       /ghi
</code></p></div>
         如果省略了<code>PT</code>标记，虽然将<code>uri=/abc/...</code>重写为<code>filename=/def/...</code>的部分运作正常，但是后续的<code>mod_alias</code>在试图将URI转换到文件名时会遭遇失效。

          <p>注意：<strong>如果需要混合使用多个将URI转换到文件名的模块时，就必须使用这个标记。</strong>。此处混合使用<code class="module"><a href="mod_alias.html">mod_alias</a></code>和<code class="module"><a href="mod_rewrite.html">mod_rewrite</a></code>就是个典型的例子。</p>
        </li>

        <li>'<strong><code>qsappend|QSA</code></strong>'(追加查询字符串)<br />
        此标记强制重写引擎在已有的替换字符串中追加一个查询字符串，而不是简单的替换。如果需要通过重写规则在请求串中增加信息，就可以使用这个标记。</li>

         <li>'<strong><code>redirect|R</code> [=<em>code</em>]</strong>'(强制<a id="redirect" name="redirect">重定向</a>)<br />
         若<em>Substitution</em>以<code>http://thishost[:thisport]/</code>(使新的URL成为一个URI)开头，可以强制性执行一个外部重定向。如果没有指定<em>code</em>，则产生一个HTTP响应码302(临时性移动)。如果需要使用在300-400范围内的其他响应代码，只需在此指定即可(或使用下列符号名称之一：<code>temp</code>(默认), <code>permanent</code>, <code>seeother</code>)。使用它可以把规范化的URL反馈给客户端，如将"<code>/~</code>"重写为"<code>/u/</code>"，或始终对<code>/u/</code><em>user</em>加上斜杠，等等。<br /><strong>注意</strong>：在使用这个标记时，必须确保该替换字段是一个有效的URL。否则，它会指向一个无效的位置！并且要记住，此标记本身只是对URL加上<code>http://thishost[:thisport]/</code>前缀，重写操作仍然会继续进行。通常，你还会希望停止重写操作而立即重定向，那么就还需要使用'L'标记。</li>

        <li>'<strong><code>skip|S</code></strong>=<em>num</em>'(跳过后继规则)<br />
        此标记强制重写引擎跳过当前匹配规则之后的<em>num</em>个规则。它可以模拟if-then-else结构：最后一个规则是then从句，而被跳过的<code>skip=N</code>个规则是else从句。注意：它和'chain|C'标记是不同的！</li>

        <li>'<strong><code>type|T</code></strong>=<em>MIME-type</em>'(强制MIME类型)<br />
        强制目标文件的<a class="glossarylink" href="../glossary.html#mime-type" title="see glossary">MIME类型</a>为<em>MIME-type</em>，可以用来基于某些特定条件强制设置内容类型。比如，下面的指令可以让<code>.php</code>文件在以<code>.phps</code>扩展名调用的情况下由<code>mod_php</code>按照PHP源代码的MIME类型(application/x-httpd-php-source)显示：
        <div class="example"><p><code>
            RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]
        </code></p></div>
        </li>
      </ul>

<div class="note"><h3>目录级重写</h3>

<p>为了在<a href="../howto/htaccess.html">.htaccess</a>文件中针对特定目录使用重写引擎，你必须<strong>同时</strong>设置"<code>RewriteEngine On</code>"和"<code>Options FollowSymLinks</code>"。如果管理员禁止了该目录的<code>FollowSymLinks</code>特性，重写引擎将不会工作，这样做的原因是处于安全方面的考虑。</p>

<p>在服务器级配置中，模式匹配是作用于整个URL的。但是在目录级配置文件<code>.htaccess</code>中使用重写引擎的时候，目录前缀(一般总是和特定的目录名称相同)将会在模式匹配前被自动<em>移除</em>并在替换完成后被自动<em>添加</em>回去。这个特性对于重写来说是非常重要的，否则你就被迫必须总是对父目录进行匹配，而这并不总是可行的。这里有一个例外：如果替换字符串以"<code>http://</code>"开头，则<strong>不会</strong>添加目录前缀，而是强制执行一个外部重定向或代理操作(如果使用了<strong>P</strong>标志的话)。参见<code class="directive"><a href="mod_rewrite.html#rewritebase">RewriteBase</a></code>指令以获得更多信息。</p>

<p>还可以在<code class="directive"><a href="core.html#directory">&lt;Directory&gt;</a></code>配置段中使用重写引擎，前缀匹配规则与在<code>.htaccess</code>中使用重写引擎时完全相同，并且这种做法更加简单。然而，为了避免前缀替换复杂化，我们还是建议尽量将重写规则放置在主服务器或虚拟主机配置部分，而不是放置在<code class="directive"><a href="core.html#directory">&lt;Directory&gt;</a></code>配置段中。</p>

<p>虽然重写规则在语法上允许放置在<code class="directive"><a href="core.html#location">&lt;Location&gt;</a></code>配置段中，但这不是必须的，并且我们也反对这样做。</p>

</div>

<div class="note"><h3>注意：绝对URL的替换</h3>
          <p>当替换字段以"<code>http://thishost[:thisport]</code>"作为前缀时，<code class="module"><a href="mod_rewrite.html">mod_rewrite</a></code>会将它自动剥离出去。在配合生成主机名部分的映射函数使用的时候，这个对隐含的外部重定向URL的简化操作是有用的而且是重要的。下面的第一个例子有助于理解这点。</p>
          <p><strong>谨记</strong>：由于此功能的存在，以"<code>http://thishost</code>"为前缀的无条件外部重定向到自身所在的服务器是无效的。要实现一个到自身的重定向，必须使用<strong>R</strong>标记。</p>
</div>

<div class="note"><h3>注意：查询字符串</h3>
      <p><em>Pattern</em>不会按照查询字符串进行匹配。为了达到这个目的，你必须使用一个带有<code>%{QUERY_STRING}</code>变量的<code class="directive"><a href="mod_rewrite.html#rewritecond">RewriteCond</a></code>指令。当然，你也可以在替换字符串中创建包含查询字符串的URL：在替换字符串串中使用问号，以标明其后的部分应该被重新注入到QUERY_STRING中。而要删除一个已有的请求串，则可以用问号来终结替换字符串。为了联合新旧查询字符串，请使用<code>[QSA]</code>标志。</p>
</div>

     <p>以下是所有可能的替换组合及其含义：</p>

      <p><strong>在服务器级配置中(<code>httpd.conf</code>)<br />
       对给定的请求"<code>GET /somepath/pathinfo</code>"：</strong><br />
      </p>

<div class="note"><pre>
<strong>给定的规则</strong>                                       <strong>得到的替换字符串</strong>
----------------------------------------------  ----------------------------------
^/somepath(.*) otherpath$1                      非法,不被支持

^/somepath(.*) otherpath$1  [R]                 非法,不被支持

^/somepath(.*) otherpath$1  [P]                 非法,不被支持
----------------------------------------------  ----------------------------------
^/somepath(.*) /otherpath$1                     /otherpath/pathinfo

^/somepath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                通过外部重定向

^/somepath(.*) /otherpath$1 [P]                 毫无意义,不被支持
----------------------------------------------  ----------------------------------
^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^/somepath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                通过外部重定向

^/somepath(.*) http://thishost/otherpath$1 [P]  毫无意义,不被支持
----------------------------------------------  ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                通过外部重定向

^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                通过外部重定向
                                                ([R]标记是多余的)

^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                通过内部代理
</pre></div>

      <p><strong>在<code>/somepath</code>的目录级配置中<br />
       (也就是<code>/physical/path/to/somepath/.htacccess</code>文件中含有：<code>RewriteBase /somepath</code>)<br />
       对给定的请求"<code>GET /somepath/localpath/pathinfo</code>"：</strong><br />
     </p>

<div class="note"><pre>
<strong>给定的规则</strong>                                       <strong>得到的替换字符串</strong>
----------------------------------------------  ----------------------------------
^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo

^localpath(.*) otherpath$1  [R]                 http://thishost/somepath/otherpath/pathinfo
                                                通过外部重定向

^localpath(.*) otherpath$1  [P]                 毫无意义,不被支持
----------------------------------------------  ----------------------------------
^localpath(.*) /otherpath$1                     /otherpath/pathinfo

^localpath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                通过外部重定向

^localpath(.*) /otherpath$1 [P]                 毫无意义,不被支持
----------------------------------------------  ----------------------------------
^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^localpath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                通过外部重定向

^localpath(.*) http://thishost/otherpath$1 [P]  毫无意义,不被支持
----------------------------------------------  ----------------------------------
^localpath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                通过外部重定向

^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                通过外部重定向
                                                ([R]标记是多余的)

^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                通过内部代理
</pre></div>

</div>
</div>
<div id="footer">
<p class="apache">本文允许自由的转载、引用、再分发，但必须保留译者署名并注明出处；详见：<a href="../translator_announcement.html#announcement">版权声明</a>。</p>
<p class="menu"><a href="index.html">模块索引</a> | <a href="directives.html">指令索引</a> | <a href="../faq/index.html">常见问题</a> | <a href="../glossary.html">词汇表</a> | <a href="../sitemap.html">站点导航</a></p></div>
</body></html>
